package net.m2technologies.open_arm.utilities;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * Copyright 2005 Mark Masterson<br> <br> Licensed under the Apache License, Version 2.0 (the "License");<br> you may
 * not use this file except in compliance with the License.<br> You may obtain a copy of the License at<br> <br>
 * http://www.apache.org/licenses/LICENSE-2.0<br> <br> Unless required by applicable law or agreed to in writing,
 * software<br> distributed under the License is distributed on an "AS IS" BASIS,<br> WITHOUT WARRANTIES OR CONDITIONS
 * OF ANY KIND, either express or implied.<br> See the License for the specific language governing permissions and<br>
 * limitations under the License.<br>
 * <p/>
 * <p>Description: </p>
 *
 * @author Mark Masterson
 * @version 0.010
 */
public class DateCalendarHelper {

    /**
     * The default formatting pattern to pass to java.text.SimpleDateFormat in order to format a java.util.Calendar as a
     * String
     */
    public static final String DEFAULT_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * Formatting pattern f�r exact timestamps
     */
    public static final String MILLISEC_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
    private static final long SECONDS_FACTOR = 1000L;

    private DateCalendarHelper() {
    }

    /**
     * Takes a java.util.Calendar and returns an integer value representing the number of <b>seconds</b> since the Epoch
     * (this is variously referred to as "UNIX time" or "C time").
     */
    public static int getUnixTimeFromCalendar(final Calendar cal) {
        final long unixTime = cal.getTime().getTime() / SECONDS_FACTOR;
        return (int) unixTime;
    }

    /**
     * Takes an integer value representing the number of seconds since the Epoch (this is variously referred to as "UNIX
     * time" or "C time") and returns a java.util.Calendar instance for the date it represents.
     */
    public static Calendar getCalendarFromUnixTime(final int unixTime) {
        final GregorianCalendar greg = new GregorianCalendar();
        final long javaTime = (long) unixTime * SECONDS_FACTOR;
        greg.setTime(new java.util.Date(javaTime));
        return greg;
    }

    /**
     * Takes an integer value representing the number of seconds since the Epoch (this is variously referred to as "UNIX
     * time" or "C time") and returns it as a String, formatted according to the DEFAULT_FORMAT_PATTERN, for the
     * java.util.Calendar date it represents.
     */
    public static String getUnixTimeAsDateString(final int unixTime) {
        final GregorianCalendar greg = (GregorianCalendar) DateCalendarHelper.getCalendarFromUnixTime(unixTime);
        return DateCalendarHelper.dateStringWandler(greg.getTime(),
                                                    DateCalendarHelper.DEFAULT_FORMAT_PATTERN);
    }

    /**
     * Takes a java.util.Calendar and returns it as a String, formatted with the DEFAULT_FORMAT_PATTERN.
     */
    public static String getCalendarAsString(final Calendar cal) {
        return DateCalendarHelper.dateStringWandler(cal.getTime(),
                                                    DateCalendarHelper.DEFAULT_FORMAT_PATTERN);
    }

    /**
     * Takes a java.util.Date and returns it as a String, formatted with the DEFAULT_FORMAT_PATTERN.
     */
    public static String getDateAsString(final java.util.Date date) {
        return DateCalendarHelper.dateStringWandler(date, DateCalendarHelper.DEFAULT_FORMAT_PATTERN);
    }

    /**
     * Takes a java.util.Calendar and returns it as a String, formatted with the pattern given as the second parameter
     * to this method.  See java.text.SimpleDateFormat for the allowed pattern Strings.
     */
    public static String getCalendarAsString(final Calendar cal, final String formattingPattern) {
        return DateCalendarHelper.dateStringWandler(cal.getTime(), formattingPattern);
    }

    /**
     * Takes a java.util.Date and returns it as a String, formatted with the pattern given as the second parameter to
     * this method.  See java.text.SimpleDateFormat for the allowed pattern Strings.
     */
    public static String getDateAsString(final java.util.Date date, final String formattingPattern) {
        return DateCalendarHelper.dateStringWandler(date, formattingPattern);
    }

    /**
     * Takes a String, which should be in the "yyyy-MM-dd HH:mm:ss" format of the DEFAULT_FORMAT_PATTERN constant, and
     * returns a Java Date object with the value of the String as the value of the Date.
     *
     * @param dateTimeString
     *
     * @return java.util.Date
     */
    public static java.util.Date getDateFromString(final String dateTimeString) {
        return stringDateWandler(dateTimeString, DEFAULT_FORMAT_PATTERN);
    }

    /**
     * Takes a String in some format, and a formatting pattern that will be used to parse it, and returns a Date with
     * the value of the dateTimeString parameter.
     *
     * @param dateTimeString
     * @param pattern
     *
     * @return java.util.Date
     */
    public static java.util.Date getDateFromString(final String dateTimeString, final String pattern) {
        return stringDateWandler(dateTimeString, pattern);
    }

    /**
     * Takes a String, which should be in the "yyyy-MM-dd HH:mm:ss" format of the DEFAULT_FORMAT_PATTERN constant, and
     * returns a Java Calendar object with the value of the String as the value of the Calendar.
     *
     * @param dateTimeString Value that should be converted to a Calendar.
     *
     * @return Calendar
     */
    public static Calendar getCalendarFromString(final String dateTimeString) {
        return DateCalendarHelper.stringCalendarWandler(dateTimeString,
                                                        DateCalendarHelper.DEFAULT_FORMAT_PATTERN);
    }

    /**
     * Takes a String in some format, and a formatting pattern that will be used to parse it, and returns a Calendar
     * with the value of the dateTimeString parameter.
     *
     * @param dateTimeString Value that should be converted to a Calendar.
     * @param pattern        java.util.SimpleDateFormat formatting pattern to use to parse the String value.
     *
     * @return Calendar
     */
    public static Calendar getCalendarFromString(final String dateTimeString, final String pattern) {
        return DateCalendarHelper.stringCalendarWandler(dateTimeString, pattern);
    }

    private static String dateStringWandler(final java.util.Date date, final String pattern) {
        final SimpleDateFormat formatter = new SimpleDateFormat();
        formatter.applyPattern(pattern);
        return formatter.format(date);
    }

    private static java.util.Date stringDateWandler(final String dateTimeString, final String pattern) {
        final SimpleDateFormat formatter = new SimpleDateFormat();
        final ParsePosition parserPos = new ParsePosition(0);
        formatter.applyPattern(pattern);
        return formatter.parse(dateTimeString, parserPos);
    }

    private static Calendar stringCalendarWandler(final String dateTimeString, final String pattern) {
        final Calendar result = Calendar.getInstance();
        result.setTime(stringDateWandler(dateTimeString, pattern));
        return result;
    }

    public static Calendar roundTwoCalendarsToDate(final Calendar calendarToChange, final Calendar referenceCalendar) {
        calendarToChange.set(Calendar.HOUR_OF_DAY, referenceCalendar.get(Calendar.HOUR_OF_DAY));
        calendarToChange.set(Calendar.MINUTE, referenceCalendar.get(Calendar.MINUTE));
        calendarToChange.set(Calendar.SECOND, referenceCalendar.get(Calendar.SECOND));
        calendarToChange.set(Calendar.MILLISECOND, referenceCalendar.get(Calendar.MILLISECOND));
        return calendarToChange;
    }
}
